package com.eian.boot.common.id.generator.segment;

import com.eian.boot.common.id.exception.IdGenerationException;
import com.eian.boot.common.id.model.Segment;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;

/**
 * Redis号段生成器
 *
 * @author alex.meng
 */
@Slf4j
@RequiredArgsConstructor
public class RedisSegmentGenerator extends AbstractSegmentGenerator {

    /**
     * 默认步长
     */
    private static final int DEFAULT_STEP = 1000;
    /**
     * Redis Key前缀
     */
    private static final String KEY_PREFIX = "id:segment:";
    private final RedissonClient redissonClient;

    @Override
    protected Segment fetchNewSegment(String bizType) {
        checkRedissonClient();
        try {
            String key = KEY_PREFIX + bizType;
            RAtomicLong atomicLong = redissonClient.getAtomicLong(key);

            // 原子性地增加步长并获取新的最大值
            long newMaxId = atomicLong.addAndGet(DEFAULT_STEP);
            long currentMaxId = newMaxId - DEFAULT_STEP;

            log.debug("获取Redis号段成功：bizType={}, range=[{}, {})", bizType, currentMaxId, newMaxId);
            return Segment.create(bizType, currentMaxId, newMaxId);
        } catch (Exception e) {
            log.error("获取Redis号段异常：bizType={}", bizType, e);
            throw new IdGenerationException("ID号段生成失败（Redis）：" + e.getMessage(), e);
        }
    }

    /**
     * 设置业务类型的起始值
     *
     * @param bizType   业务类型
     * @param initValue 初始值
     */
    public void setInitValue(String bizType, long initValue) {
        checkRedissonClient();
        try {
            String key = KEY_PREFIX + bizType;
            RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
            atomicLong.set(initValue);
            log.info("设置Redis号段初始值成功：bizType={}, initValue={}", bizType, initValue);
        } catch (Exception e) {
            log.error("设置Redis号段初始值异常：bizType={}, initValue={}", bizType, initValue, e);
            throw new IdGenerationException("设置Redis号段初始值失败：" + e.getMessage(), e);
        }
    }

    /**
     * 检查RedissonClient是否已配置
     */
    private void checkRedissonClient() {
        if (redissonClient == null) {
            throw new IdGenerationException(
                    "RedissonClient未配置，无法使用Redis号段生成器。" +
                            "\n请在application.yml中添加Redisson配置：" +
                            "\nspring.data.redis.redisson.config: |" +
                            "\n  singleServerConfig:" +
                            "\n    address: \"redis://localhost:6379\"" +
                            "\n    database: 0"
            );
        }
    }
}

